package com.ruoyi.match.controller;

/**
 * @author 宋LS
 * @version 1.0
 * @date 2020/9/9 21:49
 */


import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdWorker;
import com.ruoyi.match.service.IMatchEquipmentService;
import com.ruoyi.match.service.IMatchHealthService;

import com.ruoyi.match.domain.MatchEquipment;
import com.ruoyi.match.domain.MatchHealth;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Api(tags = "EspSocket")
@ServerEndpoint(value = "/EspSocket/{appid}")
@Component
public class EspSocket {
    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;
    private RedisTemplate redisTemplate;

    private String userid;
    /**
     * concurrent包的线程安全Map，用来存放每个客户端对应的MyWebSocket对象。
     * 在外部可以获取此连接的所有websocket对象，并能对其触发消息发送功能，我们的定时发送核心功能的实现在与此变量
     */
    public static Map<String, EspSocket> webSocketSet = new ConcurrentHashMap<>();
    private static final String ARDUNIO = "ARDUNIO";

    private IMatchEquipmentService matchEquipmentService;
    private IMatchHealthService healthService;
    private String appId;

    public String getAppId() {
        return appId;
    }

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        EspSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        EspSocket.onlineCount--;
    }


    public static EspSocket getWebSocketSet(String appid) {

        return webSocketSet.get(appid);

    }

    public static void setWebSocketSet(String appid) {
        EspSocket.webSocketSet = webSocketSet;
    }


    /**
     * 连接建立成功调用的方法
     * <p>
     * 类似dwr的onpage方法，参考之前文章中demo有
     */
    @ApiOperation("websokit建立连接")
    @OnOpen
    public void onOpen(Session session, @PathParam("appid") String appId) throws IOException {
        addOnlineCount();
        redisTemplate = SpringUtils.getBean("redisTemplate");

        matchEquipmentService = SpringUtils.getBean(IMatchEquipmentService.class);
        healthService = SpringUtils.getBean(IMatchHealthService.class);
        MatchEquipment equipment = new MatchEquipment();
        equipment.setEquipment(appId);
        List<MatchEquipment> matchEquipments = matchEquipmentService.selectMatchEquipmentList(equipment);
        this.session = session;
        if (matchEquipments.size() != 0) {
            userid = matchEquipments.get(0).getUserid();
            redisTemplate.opsForHash().put(userid, appId, "123");
            redisTemplate.expire(userid, 1, TimeUnit.MINUTES);
        } else {
            sendMessage("设备未绑定客户端！");
            session.close();
            return;
        }
        this.appId = appId.toLowerCase();
        EspSocket webSocketSet = EspSocket.getWebSocketSet(appId);
        if (webSocketSet != null) {
            webSocketSet.sendMessage("您的账号在别地登陆！！！");
            webSocketSet.getSession().close();
        } else {
            EspSocket.webSocketSet.put(appId.toLowerCase(), this);     //加入set中
            //在线数加1
            try {
                sendMessage("连接已建立成功");
            } catch (Exception e) {
                System.out.println("IO异常");
            }
        }
    }

    /**
     * 连接关闭调用的方法
     * <p>
     * 参考dwrsession摧毁方法
     */
    @OnClose
    public void onClose() {
        //连接关闭后，将此websocket从set中删除

        //在线数减1
        subOnlineCount();
        redisTemplate.opsForHash().delete(userid, appId);
        webSocketSet.remove(this.appId);

        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
//接收消息
        redisTemplate.opsForHash().put(userid, appId, "1");
        ObjectMapper mapper = new ObjectMapper();
        MatchHealth equipment = mapper.readValue(message, MatchHealth.class);
        IdWorker idWorker = new IdWorker(11, 11);
        equipment.setId(idWorker.nextId());
        equipment.setDatatime(new Date());
        equipment.setUid(userid);
        equipment.setEquipmentId(appId);
        healthService.insertMatchHealth(equipment);
//        { "temperature": 36.5, "humidity": 50, "cough": 1}
    }

    // 错误提示
    @OnError
    public void onError(Session session, Throwable error) {

    }

    //      发送消息，在定时任务中会调用此方法
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    // 发送消息，在定时任务中会调用此方法         发送user  可以自定义发送的数据
    public void sendRealData(Integer data) throws IOException {
        sendMessage(data.toString());
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }


}

